package com.neusoft.databus.core.controller;

import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.neusoft.bizcore.web.dto.result.PageResultDTO;
import com.neusoft.bizcore.web.dto.result.ResultDTO;
import com.neusoft.bizcore.web.dto.result.ResultListDTO;
import com.neusoft.bizcore.web.exception.CustomRuntimeException;
import com.neusoft.bizcore.web.support.Searchable;
import com.neusoft.databus.common.bean.CommandBean;
import com.neusoft.databus.common.dto.ResourceDTO;
import com.neusoft.databus.core.service.ResourceService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

/**
 * 资源管理控制器
 *
 * @author sunchf
 * @date 2018年12月17日 下午2:16:41
 */
@Slf4j
@Api("资源管理控制器")
@RestController
@RequestMapping(value = "/api/w/resources")
public class ResourceController {
    @Autowired
    private ResourceService resourceService;

    /**
     * 查询所有资源 <br>
     * GET <br>
     *
     * @return ResultListDTO
     */
    @ApiOperation("查询所有资源")
    @GetMapping
    public ResultListDTO<ResourceDTO> index(final Searchable searchable) {
        final ResultListDTO<ResourceDTO> result = ResultListDTO.success(this.resourceService.search(searchable));
        return result;
    }

    @ApiOperation("分页查询所有资源")
    @GetMapping("/p")
    public PageResultDTO<ResourceDTO> search(final Searchable searchable, final Pageable pageable) {
        return PageResultDTO.success(this.resourceService.search(pageable, searchable));
    }

    @ApiOperation("查询单个资源")
    @GetMapping("/{code}")
    public ResultDTO<ResourceDTO> searchByCode(@PathVariable final String code) {
        final ResourceDTO resource = this.resourceService.findByCode(code);
        return ResultDTO.success(resource);
    }

    @ApiOperation("查询单个资源")
    @GetMapping("/{code}/isExisted")
    public ResultDTO<Integer> isExisted(@PathVariable final String code) {

        return ResultDTO.success(this.resourceService.isExisted(code) ? 1 : 0);
    }

    /**
     * 创建资源 <br>
     * POST <br>
     *
     * @param dto ResourceDTO
     * @return ResultDTO<ResourceDTO>
     */
    @ApiOperation("创建资源")
    @PostMapping
    public ResultDTO<ResourceDTO> create(@RequestBody final ResourceDTO dto) {
        final ResourceDTO result = this.resourceService.create(dto);
        return ResultDTO.success(result);
    }

    /**
     * 删除资源，物理删除 <br>
     * DELETE <br>
     *
     * @param code 资源编码
     * @return ResultDTO<Void>
     * @throws CustomRuntimeException
     */
    @ApiOperation("删除资源，物理删除")
    @DeleteMapping("/{code}")
    public ResultDTO<Void> delete(@PathVariable final String code) {
        this.resourceService.delete(code);
        return ResultDTO.success();
    }

    /**
     * 资源绑定指标组（內部使用）
     *
     * @param id 资源ID
     * @param groupIdList 指标组ID列表
     * @return ResultDTO<Void>
     * @throws CustomRuntimeException
     */
    @ApiOperation("资源绑定指标组（內部使用）")
    @PutMapping("/{id}/bindById")
    public ResultDTO<ResourceDTO> bindById(@PathVariable final Long id, @RequestBody final List<Long> groupIdList) {
        final ResourceDTO result = this.resourceService.bind(id, groupIdList);
        return ResultDTO.success(result);
    }

    /**
     * 资源绑定指标组（外部使用）
     *
     * @param code 资源编码
     * @param groupCodeList 指标组编码列表
     * @return ResultDTO<Void>
     * @throws CustomRuntimeException
     */
    @ApiOperation("资源绑定指标组（外部使用）")
    @PutMapping("/{code}/bind")
    public ResultDTO<ResourceDTO> bind(@PathVariable final String code, @RequestBody final List<String> groupCodeList) {
        final ResourceDTO result = this.resourceService.bind(code, groupCodeList);
        return ResultDTO.success(result);
    }

    /**
     * 更新资源，仅更新资源的基本属性，不更新组关系
     *
     * @param code 资源编码
     * @param dto 资源DTO
     * @return ResultDTO<ResourceDTO>
     * @throws CustomRuntimeException
     */
    @ApiOperation(value = "更新资源", notes = "仅更新资源的基本属性，不更新组关系")
    @PutMapping("/{code}")
    public ResultDTO<ResourceDTO> update(@PathVariable final String code, @RequestBody final ResourceDTO dto) {
        final ResourceDTO result = this.resourceService.update(code, dto);
        return ResultDTO.success(result);
    }

    /**
     * 启用资源
     *
     * @param code 资源编码
     * @return ResultDTO<Void>
     * @throws CustomRuntimeException
     */
    @ApiOperation("启用资源")
    @PutMapping("/{code}/enable")
    public ResultDTO<Void> enable(@PathVariable final String code) {
        this.resourceService.enable(code);
        return ResultDTO.success();
    }

    /**
     * 禁用资源
     *
     * @param code 资源编码
     * @return ResultDTO<Void>
     * @throws CustomRuntimeException
     */
    @ApiOperation(" 禁用资源")
    @PutMapping("/{code}/disable")
    public ResultDTO<Void> disable(@PathVariable final String code) {
        this.resourceService.disable(code);
        return ResultDTO.success();
    }

    /**
     * 执行单次采集
     *
     * @param code 资源编码
     * @return ResultDTO<CommandBean>
     * @throws CustomRuntimeException
     */
    @ApiOperation("手动采集")
    @GetMapping("/{code}/collect")
    public ResultDTO<CommandBean> collect(@PathVariable final String code,
            @RequestParam(required = false) Map<String, Object> params) throws Exception {
        final ResultDTO<CommandBean> result = this.resourceService.collect(code, params);
        return result;
    }

    /**
     * 执行设备控制
     *
     * @param code 资源编码
     * @param metric 指标编码
     * @return ResultDTO<CommandBean>
     * @throws CustomRuntimeException
     */
    @ApiOperation("手动控制")
    @PutMapping("/{code}/control/{metric}")
    public ResultDTO<Boolean> control(@PathVariable final String code, @PathVariable final String metric)
            throws Exception {
        final ResultDTO<CommandBean> result = this.resourceService.control(code, metric);
        return ResultDTO.success(result.getData().getResourceBean().get(0).getMetrics().stream()
                .filter(it -> it.isExecutedSuccess()).count() > 0);
    }

    /**
     * 资源分布
     *
     * @return ResultDTO<Map<String, List<Long>>>
     * @throws CustomRuntimeException
     */
    @ApiOperation("资源分布")
    @GetMapping("/distribution")
    public ResultDTO<Map<String, List<Long>>> distribution() {
        final Map<String, List<Long>> datas = this.resourceService.distribution();
        return ResultDTO.success(datas);
    }

    @ApiOperation("下载资源导入模版")
    @GetMapping("/template")
    public void downloadTpl(final HttpServletResponse response) {
        final SXSSFWorkbook workbook = this.resourceService.getTpl();
        OutputStream out = null;
        try {
            out = response.getOutputStream();
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-disposition", String.format("attachment; filename=%s",
                    URLEncoder.encode(workbook.getSheetName(0) + ".xlsx", "UTF-8")));
            workbook.write(out);
            out.flush();
        } catch (final Exception e) {
            ResourceController.log.error("", e);
        } finally {
            try {
                out.close();
            } catch (final IOException e) {
                ResourceController.log.error("", e);
            }
        }

    }

    /**
     * 资源导入
     *
     * @param file
     * @return
     */
    @ApiOperation("资源导入")
    @PostMapping("/import")
    public ResultDTO<?> importTpl(@RequestParam("file") final MultipartFile file) {
        this.resourceService.importTpl(file);
        return ResultDTO.success();
    }

    /**
     * 资源导出
     *
     * @param file
     * @return
     */
    @ApiOperation("资源导出")
    @GetMapping("/export")
    public void export(final Searchable searchable, final Pageable pageable, final HttpServletResponse response) {
        this.resourceService.export(searchable, pageable, response);
    }

    @ApiOperation("子系统资源编码查询资源")
    @GetMapping("/searchByAssociate/{associate}")
    public ResultDTO<ResourceDTO> searchByAssociate(@PathVariable final String associate) {
        final ResourceDTO dto = this.resourceService.findByAssociate(associate);
        return ResultDTO.success(dto);
    }
}
